package controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.Date;

import dataStructure.LinkedList;
import entity.BookingRecord;
import entity.Member;
import entity.Staff;
import entity.Venue;

public class VenueController extends ProgramFlowControl {
	private LinkedList<Venue> venues;
	private LinkedList<Member> membes;
	private LinkedList<BookingRecord> bookingRecords;
	private Staff staff;

	public VenueController(LinkedList<Venue> venues, LinkedList<Member> members, LinkedList<BookingRecord> bookingRecords, Staff staff) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException,
			InvocationTargetException, ParseException {
		super("Venues Management");
		this.staff=staff;
		
		this.venues = venues;
		this.membes = members;
		this.bookingRecords = bookingRecords;

		this.addNewChoice("1", "1. Book Venue", this, "bookVenueAction");
		this.addNewChoice("2", "2. Check Venue Booking Status", this, "printTable");
		this.addNewChoice("3", "3. Cancel Booking", this, "canelBookingAction");
		this.setTeminateOption("x", "Press x to return to Main Menu", this, "clearUp");
	}

	public void begin() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, IOException {
		System.out.println("VenueController.begin()");
		this.flowControl();
	}

	public void bookVenueAction() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		this.printTable();

		String memberID = UserInputControl.getStrInput("Member ID: ", "[0-9]{6}");
		if (memberID != null) {
			System.out.print("Input Venue type('TableTennis', 'Tennis', 'Badminton' or 'Squash'):");
			String venueType = in.readLine();
			if (venueType.equals("TableTennis") || venueType.equals("Tennis") || venueType.equals("Badminton") || venueType.equals("Squash")) {
				int startHour = UserInputControl.getIntInput("Starting Hour: ", "2");
				if (startHour >= 8 && startHour <= 22) {
					int endHour = UserInputControl.getIntInput("EndingHour: ", "2");
					if (endHour >= 8 && endHour <= 22 && startHour < endHour) {
						this.bookVenue(venueType, memberID, startHour, endHour);
					}
				}
			}
		}
	}

	public void bookVenue(String venueType, String memberID, int startHour, int endHour) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {
		Member result = this.membes.searchContent("id", memberID);
		Venue venue = this.venues.searchContent("type", venueType);

		if (result != null && startHour >= 8 && startHour <= 22 && endHour >= 8 && endHour <= 22 && startHour < endHour) {
			String timeslot[] = venue.getBookingSlot();

			int i = startHour;
			while (timeslot[i - 8].equals("0") && i < endHour) {
				i++;
			}

			if (i == endHour) {
				for (i = 0; i <= endHour - startHour; i++) {
					timeslot[startHour - 8 + i] = memberID;
				}
				venue.setBookingSlot(timeslot);

				String newRecordID = this.getNewID(this.bookingRecords);
				this.bookingRecords.addContent(new BookingRecord(newRecordID, new Date(), staff.getStaffName(), (String) result.getAttrVal("id"), venue.getVenueID(), startHour, endHour));
			}
		}
	}

	private String getNewID(LinkedList<?> list) {
		String temp = Integer.toString(list.getLength() + 1);
		int length= temp.length();

		String newID = "";
		for (int i = 0; i < 6 - length; i++) {
			newID+="0";
		}
		return newID.concat(temp);
	}

	public void canelBookingAction() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		String memberID = UserInputControl.getStrInput("Member ID: ", "[0-9]{6}");
		if (memberID != null) {
			System.out.print("Input Venue type('TableTennis', 'Tennis', 'Badminton' or 'Squash'):");
			String venueType = in.readLine();
			if (venueType.equals("TableTennis") || venueType.equals("Tennis") || venueType.equals("Badminton") || venueType.equals("Squash")) {
				int startHour = UserInputControl.getIntInput("Starting Hour: ", "2");
				if (startHour >= 8 && startHour <= 21) {
					this.canelBooking(venueType, memberID, startHour);
				}
			}
		}
	}

	public void canelBooking(String venueType, String memberID, int startHour) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {
		Member result = this.membes.searchContent("id", memberID);
		Venue venue = this.venues.searchContent("type", venueType);

		if (result != null && startHour >= 8 && startHour <= 21) {
			String timeslot[] = venue.getBookingSlot();

			int i = 0;
			while (timeslot[startHour - 8 + i].equals(memberID)) {
				timeslot[startHour - 8 + i] = "0";
				i++;
			}
			
			String newRecordID = this.getNewID(this.bookingRecords);
			this.bookingRecords.addContent(new BookingRecord(newRecordID, new Date(), staff.getStaffName(), (String) result.getAttrVal("id"), venue.getVenueID(), 0, 0));
		}
	}

	public void printTable() throws SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException, NullPointerException {
		printBorder();

		System.out.print("|    Venue    ");
		for (int i = 8; i <= 21; i++)
			System.out.print("| " + Integer.toString(i / 10) + Integer.toString(i % 10) + " ");
		System.out.println("|");

		printBorder();

		printSlots(venues.searchContent("type", "Tennis"));
		printSlots(venues.searchContent("type", "TableTennis"));
		printSlots(venues.searchContent("type", "Squash"));
		printSlots(venues.searchContent("type", "Badminton"));
	}

	private void printSlots(Venue venue) {
		System.out.print('|' + venue.getType());

		for (int i = 0; i < 13 - venue.getType().length(); i++)
			System.out.print(' ');
		
		String[] bookingSlot = venue.getBookingSlot();
		String status = "";
		for (int i = 0; i < 14; i++) {
			if (bookingSlot[i].equals("0")) {
				status = "    ";
			} else {
				status = " XX ";
			}

			System.out.print('|' + status);
		}

		System.out.println('|');
		printBorder();
	}

	private void printBorder() {
		System.out.println("-------------------------------------------------------------------------------------");
	}

	public void clearUp() {
	}
}
